import mailbox, urllib2, cStringIO, gzip

from network import _httpMailbox, _ftpMailbox
from mailmigration import errors
from mailmigration.formats import message

class MailmanGZ(_httpMailbox, _ftpMailbox, mailbox.mbox):
    """A Mailman compressed mbox archive.
        Downloaded via HTTP (urllib2).
    """
    _mangle_from_ = False
    def __init__(self, url, factory=message.MailmanMessage, create=False,
                 archive=True,
                 user_agent='Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'):
        """Initialize a MailmanGZ instance."""
        #We call the httpMailbox init to setup the actual network mechanics,
        #but do not call the mbox init because we will handle setting up the
        #file-like object in self._file ourselves.
        #Also note that we do not send on any args for handlers, as urllib2
        #defaults to adding several HTTP ones that serve our purpose.
        _httpMailbox.__init__(self, url, factory, create, user_agent)
        self._toc = {}
        self._archive = archive
        self._toc = None
        self._next_key = 0
        # The following are always False for this subclass
        self._pending = False   # No changes require rewriting the file.
        self._locked = False
        if url.endswith('http', 0, 4):
            _httpMailbox._refresh(self)
            #Substite a StringIO instance so we can seek and tell
            f = cStringIO.StringIO(self._response.read())
            #wrapped in GzipFile if compressed
            if self._response.headers.type == 'x-gzip' or \
               self._response.url.endswith('gz', -2):
                self._file = gzip.GzipFile(fileobj=f)
            else:
                self._file = f
        elif url.endswith('ftp', 0, 3):
            _ftpMailbox._refresh(self)
            #Substite a StringIO instance so we can seek and tell
            f = cStringIO.StringIO(self._response.read())
            #wrapped in GzipFile if compressed
            if self._response.url.endswith('gz', -2):
                self._file = gzip.GzipFile(fileobj=f)
            else:
                self._file = f
        else:
            mailbox.mbox.__init__(self, url, factory, create)
            self._file = gzip.GzipFile(fileobj=self._file)
        self._message_factory = factory

    def _generate_toc(self):
        """Update table of contents mapping.
            If this mailbox is a complete archive for the month, we can cache
            the complete contents. If not, we should re-download.
        """
        if not self._archive:
            self._refresh()
        mailbox.mbox._generate_toc(self)

    def _install_message(self, message):
        raise errors.ReadOnlyMailboxError('%s mailboxes are read-only.' % self.__class__.__name__)

    def _append_message(self, message):
        raise errors.ReadOnlyMailboxError('%s mailboxes are read-only.' % self.__class__.__name__)

    def iterkeys(self):
        return mailbox.mbox.iterkeys(self)

    def has_key(self, key):
        return mailbox.mbox.has_key(self, key)

    def __len__(self):
        return mailbox.mbox.__len__(self)

    def get_message(self, key):
        return mailbox.mbox.get_message(self, key)

    def get_string(self, key, from_=True):
        return mailbox.mbox.get_string(self, key, from_)

    def get_file(self, key, from_=True):
        return mailbox.mbox.get_file(self, key, from_)

    def flush(self):
        """Write any pending changes to disk."""
        return  # Maildir changes are always written immediately.

    def lock(self):
        """Lock the mailbox."""
        return

    def unlock(self):
        """Unlock the mailbox if it is locked."""
        return

    def close(self):
        """Flush and close the mailbox."""
        return

